<template>
	<scroll-view class="msg-list model-audio" :scroll-x="false" :scroll-y="true"
		:scroll-with-animation="false" :scroll-top="scrollTop" @tap="hideCopyBtn">
		<view class="list" v-if="lists && lists.length > 0">
			<block v-for="(item, index) in lists" :key="index">
				<view class="row-ai" v-if="item.user == 'AI'">
					<view class="message" :data-index="index">
						<view class="avatar">
							<img :src="aiAvatar" />
						</view>
						<view class="text markdown-body">
							<textComponent :text="item.message"></textComponent>
							<view class="tools">
								<view>
									<view class="btn" @click="copyText(item.message)">
										<image class="icon" src="/static/images/ic_copy.png"></image>
										<span>{{ '复制内容' | lang }}</span>
									</view>
								</view>
								<view>
									<view class="btn" :title="'重新回答' | lang" @tap="retry(index - 1)" style="margin-right: 0;">
										<image class="icon" src="/static/images/ic_retry.png"></image>
									</view>
								</view>
							</view>

						</view>
					</view>
				</view>
				<view class="row-user" v-else>
					<view class="message">
						<view class="avatar">
							<img :src="userAvatar" />
						</view>
						<view class="text markdown-body" @longpress="showCopyBtn" :data-text="item.message">
							<textComponent :text="item.message"></textComponent>
						</view>
					</view>
				</view>
			</block>
			<view class="row-ai" v-if="writing || writingText">
				<view class="message">
					<view class="avatar">
						<img :src="aiAvatar" />
					</view>
					<view class="text markdown-body">
						<textComponent :text="writingText" :writing="!!(writing || writingText)"></textComponent>
						<view class="tools">
							<view>
								<view class="btn" @click="stopFetch">
									<image class="icon" src="/static/images/ic_stop.png"></image>
									<span>{{ '停止回复' | lang }}</span>
								</view>
							</view>
						</view>
					</view>
				</view>
			</view>

			<view class="btn-copy" :style="'left:' + copyBtnLeft +'px;top:' + copyBtnTop + 'px;'" @tap="copyText(copyBtnText)">{{ '复制' | lang }}</view>
		</view>
		<welcome v-else module="chat" :title="welcome.title" :desc="welcome.desc" :tips="welcome.tips" @use="quickMessage"></welcome>
	</scroll-view>

</template>

<script>
	const app = getApp()

	import TextComponent from '@/components/message/text'
	import Welcome from '@/components/welcome/index2'
	import 'katex/dist/katex.min.css'
	import '@/static/styles/lib/tailwind.css'
	import '@/static/styles/lib/highlight.scss'
	import '@/static/styles/lib/github-markdown.scss'


	export default {
		components: {
			TextComponent,
			Welcome
		},
		props: {
			aiName: {
				type: String,
				default: ''
			},
			aiIndex: {
				type: Number,
				default: 0
			},
			activeAiIndex: {
				type: Number,
				default: 0
			},
			welcome: {
				type: Object,
				default: {}
			},
			userAvatar: {
				type: String,
				default: '/static/img/ic_user.png'
			},
			aiAvatar: {
				type: String,
				default: '/static/img/ic_ai.png'
			}
		},
		watch: {
			activeAiIndex: {
				handler() {
					if (this.aiIndex >= this.activeAiIndex - 1 && this.aiIndex <= this.activeAiIndex + 1 && this.lists === null) {
						this.getHistoryMsg()
					}
				},
				immediate: true
			}
		},
		data() {
			return {
				siteroot: '',
				group_id: 0,
				lists: null,
				message: '',
				writingText: '',
				writing: false,
				page: 1,
				pagesize: 10,
				scrollTop: 0,
				copyBtnLeft: -200,
				copyBtnTop: 0,
				copyBtnText: '',
				copyBtnTime: 0,
				textStacks: [],
				textOutputSi: 0,
				fetchCtrl: null
			};
		},
		mounted() {
			this.setData({
				siteroot: app.globalData.siteroot.replace('/web.php', '')
			});
		},
		methods: {
			async sendText(message) {
				if (this.writing) {
					return
				}
				message = this.trim(message)
				if (!message) {
					app.globalData.util.message('请输入你的问题')
					return
				}

				if (this.textOutputSi) {
					clearInterval(this.textOutputSi)
					this.textOutputSi = 0
					this.textStacks = []
				}

				this.lists.push({
					user: '我',
					message: message
				});
				this.setMessage('')
				this.writing = true
				this.scrollToBottom()

				const headers = new Headers();
				headers.append('Content-Type', 'application/json');
				headers.append('X-site', uni.getStorageSync('sitecode'));
				const url = this.siteroot + '/web.php/chat/sendText'
				const data = {
					message: message,
					ai: this.aiName
				}
				this.fetchCtrl = new AbortController()
				const response = await fetch(url, {
					method: 'POST',
					signal: this.fetchCtrl.signal,
					headers: headers,
					body: JSON.stringify(data),
				});
				if (!response.ok) {
					this.writing = false
					app.globalData.util.message(response.statusText)
					return
				}
				const reader = response.body.getReader();
				const decoder = new TextDecoder('utf-8');
				let done = false;
				let curAiMsg = '';

				this.textOutputSi = setInterval(() => {
					if (this.textStacks.length > 0) {
						this.writingText += this.textStacks.shift();
						this.scrollToBottom()
					} else if (!this.writing) {
						clearInterval(this.textOutputSi)
						this.textOutputSi = 0
						if (this.writingText) {
							this.lists.push({
								user: 'AI',
								message: this.writingText
							});
						}
						this.writingText = '';

						setTimeout(() => {
							this.scrollToBottom();
						}, 200)
					}
				}, 20)

				while (!done) {
					this.scrollToBottom()
					const {
						value,
						done: readerDone
					} = await reader.read();
					if (value) {
						let char = decoder.decode(value);
						if (char === '\n' && curAiMsg.endsWith('\n')) {
							continue;
						}
						if (char) {
							if (char.indexOf('[error]') !== -1) {
								this.writing = false;
								this.writingText = '';
								this.lists.pop();
								const error = char.replace('[error]', '')
								if (error.indexOf('请登录') !== -1) {
									this.setMessage(message)
									app.globalData.util.toLogin(error)
								} else if (error.indexOf('请充值') !== -1) {
									const _this = this
									app.globalData.util.message(error, 'error', function() {
										_this.toPay()
									});
								} else {
									app.globalData.util.message(error, 'error');
								}
								break;
							}
							this.writing = true;

							for (var i = 0; i < char.length; i++) {
								this.textStacks.push(char[i])
							}
						}
					}
					done = readerDone;
				}

				this.writing = false;
			},

			stopFetch() {
				const writingText = this.writingText
				this.writing = false
				this.fetchCtrl.abort()
				setTimeout(() => {
					if (!writingText) {
						this.lists.pop()
					}
				}, 50)
			},

			retry(index) {
				const _this = this
				uni.showModal({
					title: this.$lang('提示'),
					content: this.$lang('确定重新回答吗？'),
					confirmText: this.$lang('确定'),
					cancelText: this.$lang('取消'),
					success: function(res) {
						if (res.confirm) {
							_this.sendText(_this.lists[index].message)
						}
					}
				})
			},
			setMessage(message) {
				this.$emit('setMessage', message)
			},
			getHistoryMsg() {
				app.globalData.util
					.request({
						url: '/chat/getHistoryMsg',
						data: {
							ai: this.aiName,
							page: this.page,
							pagesize: this.pagesize
						},
						loading: false
					})
					.then((res) => {
						this.setData({
							lists: res.data.list
						});
						this.$nextTick(() => {
							setTimeout(() => {
								this.scrollToBottom();
							}, 300)
						})
					});
			},

			scrollToBottom() {
				setTimeout(() => {
					let query = uni.createSelectorQuery().in(this);
					query.select('.list').boundingClientRect((res) => {
						if (res) {
							this.setData({
								scrollTop: parseInt(res.height)
							});
						}
					});
					query.exec((res) => {});
				}, 200);
			},

			copyText(text) {
				let textarea = document.createElement("textarea");
				textarea.value = text;
				textarea.readOnly = "readOnly";
				textarea.style = "width:0;height:0;";
				document.body.appendChild(textarea);
				textarea.select();
				textarea.setSelectionRange(0, text.length);
				app.globalData.util.message('已复制');
				document.execCommand("copy");
				textarea.remove();
				this.hideCopyBtn()
			},

			quickMessage(text) {
				this.$emit('setMessage', text)
			},

			showCopyBtn(e) {
				let query = uni.createSelectorQuery().in(this);
				query.select('.list').boundingClientRect((res) => {
					if (res) {
						let x = parseInt(e.touches[0].pageX);
						let y = parseInt(e.touches[0].pageY - res.top);
						console.log('pageY', e.touches[0].pageY)
						console.log('listTop', res.top)
						if (e.touches[0].pageY < 110) {
							y = y + 90
						}
						this.copyBtnLeft = x - 30;
						this.copyBtnTop = y - 60;
						this.copyBtnText = e.currentTarget.dataset.text;
						this.copyBtnTime = this.getTime()
					}
				});
				query.exec((res) => {});
			},
			getTime() {
				return new Date().getTime()
			},
			hideCopyBtn() {
				const now = this.getTime()
				if (this.copyBtnLeft > 0 && now - this.copyBtnTime > 500) {
					this.copyBtnLeft = -200;
					this.copyBtnText = '';
					this.copyBtnTime = 0
				}
			},
			trim(str) {
				return str.replace(/(^\s*)|(\s*$)/g, '');
			},
			isGpt4(name) {
        return app.globalData.util.isGpt4(name)
			},
			toPay() {
				if (this.isGpt4(this.aiName)) {
					uni.navigateTo({
						url: '/pages/pay/pay?type=point'
					});
				} else {
					uni.navigateTo({
						url: '/pages/pay/pay?type=vip'
					});
				}
			}
		}
	}
</script>

<style>
	.msg-list {
		width: 100%;
		height: 100%;
		top: 0;
		bottom: 132rpx;
		left: 0;
		box-sizing: border-box;
		overflow: hidden;
	}
	.message {
	    display: flex;
	    justify-content: flex-start;
	    padding: 40rpx 40rpx;
	    border-top: 2rpx solid #eee;
	}

	.message:last-child {
	    border-bottom: 0;
	}

	.message .text {
	    width: 596rpx;
	    color: #343541;
	    line-height: 52rpx;
	    font-size: 32rpx;
	    word-break: break-all;
	    padding: 4rpx 0;
	    overflow: hidden;
	}

	.message .text span {
	    display: inline;
	}

	.message .avatar {
	    width: 48rpx;
	    height: 48rpx;
	    background: none;
	    margin-right: 30rpx;
	    color: #fff;
	    font-size: 28rpx;
	    border-radius: 8rpx;
	    display: flex;
	    align-items: center;
	    justify-content: center;
	    margin-top: 4rpx;
	    overflow: hidden;
	}

	.message .avatar image,
	.message .avatar img {
	    width: 48rpx;
	    height: 48rpx;
	}

	.model-text .row-user {
	    background: #fff;
	}

	.btn-copy {
		position: absolute;
		width: 120rpx;
		height: 60rpx;
		line-height: 60rpx;
		color: #04BABE;
		z-index: 99;
		background: #fff;
		text-align: center;
		border-radius: 10rpx;
		font-size: 28rpx;
		box-shadow: 0 0 20rpx rgba(0, 0, 0, 0.2);
	}
	.model-audio .message {
	    padding: 20rpx 20rpx;
	    border: none;
	}
	.model-audio .message .text {
	    max-width: 610rpx;
	    width: auto;
	    border-radius: 30rpx;
	    display: block;
	    padding: 20rpx 40rpx;
	    box-sizing: border-box;
	}
	.model-audio .row-user .message {
	    display: block;
	    width: 100%;
	    float: right;
	    padding: 20rpx 8rpx 20rpx 0;
	    position: relative;
	}
	.model-audio .row-user .message .avatar {
	    position: absolute;
	    right: 20rpx;
	    top: 24rpx;
	    margin-right: 0;
	}
	.model-audio .row-user .message .text {
	    float: right;
	    background-color: #86e4e0;
	    margin-right: 80rpx;
	    border-top-right-radius: 4rpx;
	}
	.model-audio .row-user .message .text .h2w-light {
	    color: #fff !important;
	}

	.model-audio .row-ai .message .text {
	    float: right;
	    background: rgba(255, 255, 255, 0.8);
	    color: #343541;
	    border-top-left-radius: 4rpx;
	}
	.tools {
		display: flex;
		align-items: center;
		justify-content: space-between;
		margin-top: 12rpx;
	}

	.tools .btn {
		font-size: 32rpx;
		color: #04BABE;
		display: flex;
		align-items: center;
		float: left;
		margin-right: 10rpx;
	}

	.tools .btn:active {
		opacity: 0.6;
	}

	.tools .btn .icon {
		width: 32rpx;
		height: 32rpx;
		margin-right: 6rpx;
	}
</style>
